import json
import os

from http_server import Response
from log import Log

log = Log(tag='Config')

__CONF_FILE_NAME = 'config.json'
__CONF_BACKUP_NAME = 'config.backup.json'


def backup_config():
    try:
        os.rename(__CONF_FILE_NAME, __CONF_BACKUP_NAME)
        return True
    except Exception as e:
        log.error('Error on backup config file', e)
        return False


def write_config(json_str):
    f = open(__CONF_FILE_NAME, 'w')
    f.write(json_str)
    f.close()


def revert_config():
    try:
        os.rename(__CONF_BACKUP_NAME, __CONF_FILE_NAME)
    except Exception as e:
        log.error('Error on Revert config', e)
    print('----OK----')


class Configuration:
    @staticmethod
    def set_config(json_str):
        try:
            config_json = json.loads(json_str)
        except Exception as e:
            log.error('Invalidate Configuration', e)
            return e

        error = Configuration.validate(config_json)
        if error:
            log.error('Invalidate Configuration JSON: %s' % error)
            return error

        if not backup_config():
            return 'Config backup fail!'
        try:
            write_config(json_str)
        except Exception as e:
            log.error('Error on write config file', e)
            return e
        print('----OK----')

    @staticmethod
    def validate(conf):
        log.info('Load Config [%s]' % conf)
        if 'net' not in conf:
            return 'net config not exists'
        net = conf['net']
        if 'ap' not in net or len(net['ap']) <= 0:
            return 'NET: No wifi ssid conf'
        ap = net['ap']
        if 'ssid' not in ap:
            return 'AP, No SSID Config'
        if 'password' not in ap:
            return 'AP, No Password Config'
        if 'ip' not in net:
            return 'NET: No Ip Conf'
        if 'netmask' not in net:
            return 'NET: No NetMask Conf'
        if 'gateway' not in net:
            return 'NET: No GateWay Conf'
        if 'dns' not in net:
            return 'NET: No DNS Conf'
        if 'dhcp' not in net:
            return 'NET: No DHCP Config'

        if 'api' not in conf:
            return 'api config is not exists!'
        api = conf['api']
        if 'commitUrl' not in api:
            return 'API: No commitUrl Conf'
        if 'warehouseId' not in api:
            return 'API:No warehouseId Conf'
        if 'entityId' not in api:
            return 'API:No entityId Conf'
        if 'entityId' not in api:
            return 'API:No entityId Conf'

    def __init__(self, filename):
        try:
            os.stat(filename)
        except Exception as e:
            log.error('No Configuration File %s ' % filename, e)
            return
        self.__filename = filename
        self.__is_ready = False
        self.__conf = None
        self.err_msg = None

    def load(self):
        try:
            f = open(self.__filename)
            json_str = f.read()
            f.close()
        except Exception as e:
            log.error('Error On Read Config File', e)
            self.__is_ready = False
            return False

        try:
            self.__conf = json.loads(json_str)
            error_msg = self.validate(self.__conf)
            self.err_msg = error_msg
            if error_msg:
                log.error(error_msg)
                self.__is_ready = False
                return False
        except Exception as e:
            log.error('Error on Resolver config json', e)
            self.__is_ready = False
            return False
        self.__is_ready = True
        return True

    def net(self, key=None):
        if not key:
            return self.__conf['net']
        if key in self.__conf['net']:
            return self.__conf['net'][key]

    def api(self, key=None):
        if not key:
            return self.__conf['api']
        if key in self.__conf['api']:
            return self.__conf['api'][key]

    def is_ready(self):
        return self.__is_ready


DEFAULT_CONF_FILE = 'config.json'
config = None


def auto_load_conf():
    global config
    config = Configuration(DEFAULT_CONF_FILE)
    config.load()
    if config.is_ready():
        log.info('Load Config Success!')
    else:
        log.error('Load Config Error!')


auto_load_conf()


class ConfigController:
    def post(self, req):
        log.debug('Config Http', req)
        body_size = req.body.get_length()
        body = req.body.read_all_as_string()
        log.debug('Http Body[%s]: %s' % (body_size, body))
        error = Configuration.set_config(body.decode())
        if error:
            return Response(status=400, body=str(error).encode())
        return Response(body=b'{"code": 200,"msg":"ok"}')
